'for await...of' लूप आणि कस्टम असिंक इटरेटर हेल्पर्स वापरून जावास्क्रिप्टमध्ये असिंक्रोनस इटिरेशनमध्ये प्राविण्य मिळवा. व्यावहारिक उदाहरणांसह स्ट्रीम प्रोसेसिंग आणि डेटा हँडलिंग सुधारा.
जावास्क्रिप्ट असिंक इटरेटर हेल्पर: फॉर ईच - स्ट्रीम प्रोसेसिंग पुनरावृत्ती
असिंक्रोनस प्रोग्रामिंग हे आधुनिक जावास्क्रिप्ट डेव्हलपमेंटचा आधारस्तंभ आहे, जे ऍप्लिकेशन्सना मुख्य थ्रेड ब्लॉक न करता वेळखाऊ ऑपरेशन्स हाताळण्यास सक्षम करते. ECMAScript 2018 मध्ये सादर केलेले असिंक इटरेटर्स, असिंक्रोनसपणे डेटा स्ट्रीम्सवर प्रक्रिया करण्यासाठी एक शक्तिशाली यंत्रणा प्रदान करतात. हा ब्लॉग पोस्ट असिंक इटरेटर्सच्या संकल्पनेचा सखोल अभ्यास करतो आणि स्ट्रीम प्रोसेसिंग सुव्यवस्थित करण्यासाठी असिंक्रोनस 'फॉर ईच' हेल्पर फंक्शन कसे लागू करावे हे दाखवतो.
असिंक इटरेटर्स समजून घेणे
असिंक इटरेटर एक ऑब्जेक्ट आहे जो AsyncIterator इंटरफेसचे पालन करतो. हे एक next() मेथड परिभाषित करते जी एक प्रॉमिस (promise) परत करते, जे दोन प्रॉपर्टीज असलेल्या ऑब्जेक्टमध्ये रिझॉल्व्ह होते:
value: अनुक्रमातील पुढील व्हॅल्यू.done: इटरेटर पूर्ण झाला आहे की नाही हे दर्शवणारे बुलियन.
असिंक इटरेटर्स सामान्यतः नेटवर्क स्ट्रीम्स, फाइल सिस्टीम किंवा डेटाबेससारख्या असिंक्रोनस स्रोतांकडून डेटा वापरण्यासाठी वापरले जातात. for await...of लूप असिंक इटरेबल्सवर पुनरावृत्ती करण्यासाठी सोयीस्कर सिंटॅक्स प्रदान करतो.
उदाहरण: फाईलमधून असिंक्रोनसपणे वाचणे
अशा परिस्थितीचा विचार करा जिथे तुम्हाला मुख्य थ्रेड ब्लॉक न करता एक मोठी फाईल ओळी-ओळीने वाचायची आहे. तुम्ही हे असिंक इटरेटर वापरून साध्य करू शकता:
const fs = require('fs');
const readline = require('readline');
async function* readFileLines(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
for await (const line of rl) {
yield line;
}
}
async function processFile(filePath) {
for await (const line of readFileLines(filePath)) {
console.log(`Line: ${line}`);
}
}
// Example usage
processFile('path/to/your/file.txt');
या उदाहरणात, readFileLines एक असिंक जनरेटर फंक्शन आहे जे फाईलची प्रत्येक ओळ वाचल्यावर यील्ड (yield) करते. processFile फंक्शन नंतर for await...of वापरून ओळींवर पुनरावृत्ती करते, प्रत्येक ओळीवर असिंक्रोनसपणे प्रक्रिया करते.
असिंक 'फॉर ईच' हेल्पर लागू करणे
जरी for await...of लूप उपयुक्त असला तरी, जेव्हा तुम्हाला स्ट्रीममधील प्रत्येक घटकावर गुंतागुंतीच्या क्रिया करायच्या असतात तेव्हा ते शब्दबंबाळ होऊ शकते. एक असिंक 'फॉर ईच' हेल्पर फंक्शन पुनरावृत्ती तर्क (iteration logic) गुंडाळून ही प्रक्रिया सोपी करू शकते.
मूलभूत अंमलबजावणी
येथे असिंक 'फॉर ईच' फंक्शनची एक मूलभूत अंमलबजावणी आहे:
async function asyncForEach(iterable, callback) {
for await (const item of iterable) {
await callback(item);
}
}
हे फंक्शन एक असिंक इटरेबल आणि एक कॉलबॅक फंक्शन वितर्क म्हणून घेते. ते for await...of वापरून इटरेबलवर पुनरावृत्ती करते आणि प्रत्येक आयटमसाठी कॉलबॅक फंक्शनला कॉल करते. पुढील आयटमवर जाण्यापूर्वी कॉलबॅक पूर्ण होण्याची प्रतीक्षा करायची असल्यास कॉलबॅक फंक्शन देखील असिंक्रोनस असावे.
उदाहरण: API मधून डेटावर प्रक्रिया करणे
समजा तुम्ही अशा API मधून डेटा मिळवत आहात जो आयटम्सचा स्ट्रीम परत करतो. प्रत्येक आयटम आल्यावर त्यावर प्रक्रिया करण्यासाठी तुम्ही असिंक 'फॉर ईच' हेल्पर वापरू शकता:
async function* fetchDataStream(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
return;
}
// Assuming the API returns JSON chunks
const chunk = decoder.decode(value);
const items = JSON.parse(`[${chunk.replace(/\}\{/g, '},{')}]`); //Split chunks into valid json array
for(const item of items){
yield item;
}
}
} finally {
reader.releaseLock();
}
}
async function processItem(item) {
// Simulate an asynchronous operation
await new Promise(resolve => setTimeout(resolve, 100));
console.log(`Processing item: ${JSON.stringify(item)}`);
}
async function main() {
const apiUrl = 'https://api.example.com/data'; // Replace with your API endpoint
await asyncForEach(fetchDataStream(apiUrl), processItem);
console.log('Finished processing data.');
}
// Example usage
main();
या उदाहरणात, fetchDataStream API मधून डेटा मिळवते आणि प्रत्येक आयटम प्राप्त झाल्यावर तो यील्ड (yield) करते. processItem फंक्शन प्रत्येक आयटमवर एका असिंक्रोनस ऑपरेशनचे अनुकरण करते. asyncForEach हेल्पर नंतर पुनरावृत्ती आणि प्रक्रिया तर्क (logic) सोपे करतो.
सुधारणा आणि विचार करण्यासारख्या गोष्टी
त्रुटी हाताळणी (Error Handling)
असिंक्रोनस पुनरावृत्ती दरम्यान उद्भवणाऱ्या त्रुटी हाताळणे महत्त्वाचे आहे. तुम्ही अपवाद (exceptions) पकडण्यासाठी आणि हाताळण्यासाठी कॉलबॅक फंक्शनला try...catch ब्लॉकमध्ये गुंडाळू शकता:
async function asyncForEach(iterable, callback) {
for await (const item of iterable) {
try {
await callback(item);
} catch (error) {
console.error(`Error processing item: ${item}`, error);
// You can choose to re-throw the error or continue processing
}
}
}
समवर्ती नियंत्रण (Concurrency Control)
डीफॉल्टनुसार, असिंक 'फॉर ईच' हेल्पर आयटम्सवर अनुक्रमे प्रक्रिया करतो. जर तुम्हाला आयटम्सवर समवर्तीपणे प्रक्रिया करायची असेल, तर तुम्ही समवर्ती ऑपरेशन्सची संख्या मर्यादित करण्यासाठी प्रॉमिस पूल (Promise pool) वापरू शकता:
async function asyncForEachConcurrent(iterable, callback, concurrency) {
const executing = [];
for await (const item of iterable) {
const p = callback(item).then(() => executing.splice(executing.indexOf(p), 1));
executing.push(p);
if (executing.length >= concurrency) {
await Promise.race(executing);
}
}
await Promise.all(executing);
}
async function processItem(item) {
// Simulate an asynchronous operation
await new Promise(resolve => setTimeout(resolve, 100));
console.log(`Processing item: ${JSON.stringify(item)}`);
}
async function main() {
const apiUrl = 'https://api.example.com/data'; // Replace with your API endpoint
await asyncForEachConcurrent(fetchDataStream(apiUrl), processItem, 5); // Concurrency of 5
console.log('Finished processing data.');
}
या उदाहरणात, asyncForEachConcurrent समवर्ती कॉलबॅक एक्झिक्यूशनची संख्या निर्दिष्ट कॉन्करन्सी पातळीपर्यंत मर्यादित करते. मोठ्या डेटा स्ट्रीम्स हाताळताना हे कार्यप्रदर्शन सुधारू शकते.
रद्द करणे (Cancellation)
काही प्रकरणांमध्ये, तुम्हाला पुनरावृत्ती प्रक्रिया अकाली रद्द करण्याची आवश्यकता असू शकते. तुम्ही AbortController वापरून हे साध्य करू शकता:
async function asyncForEach(iterable, callback, signal) {
for await (const item of iterable) {
if (signal && signal.aborted) {
console.log('Iteration aborted.');
return;
}
await callback(item);
}
}
async function main() {
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => {
controller.abort(); // Abort after 2 seconds
}, 2000);
const apiUrl = 'https://api.example.com/data'; // Replace with your API endpoint
await asyncForEach(fetchDataStream(apiUrl), processItem, signal);
console.log('Finished processing data.');
}
या उदाहरणात, asyncForEach फंक्शन प्रत्येक पुनरावृत्तीपूर्वी signal.aborted प्रॉपर्टी तपासते. जर सिग्नल रद्द झाला असेल, तर पुनरावृत्ती थांबवली जाते.
वास्तविक-जगातील अनुप्रयोग
असिंक इटरेटर्स आणि असिंक 'फॉर ईच' हेल्पर वास्तविक-जगातील विस्तृत परिस्थितींमध्ये लागू केले जाऊ शकतात:
- डेटा प्रोसेसिंग पाइपलाइन्स: डेटाबेस किंवा फाइल सिस्टीममधून मोठ्या डेटासेट्सवर प्रक्रिया करणे.
- रिअल-टाइम डेटा स्ट्रीम्स: वेब सॉकेट्स, मेसेज क्यू किंवा सेन्सर नेटवर्क्समधून डेटा हाताळणे.
- API कंजम्पशन: आयटम्सचे स्ट्रीम्स परत करणाऱ्या API मधून डेटा मिळवणे आणि त्यावर प्रक्रिया करणे.
- इमेज आणि व्हिडिओ प्रोसेसिंग: मोठ्या मीडिया फाइल्सवर तुकड्यांमध्ये प्रक्रिया करणे.
- लॉग विश्लेषण: मोठ्या लॉग फाइल्सचे ओळी-ओळीने विश्लेषण करणे.
उदाहरण - आंतरराष्ट्रीय स्टॉक डेटा: अशा ऍप्लिकेशनचा विचार करा जो विविध आंतरराष्ट्रीय एक्सचेंजेसवरून रिअल-टाइम स्टॉक कोट्स मिळवतो. डेटा स्ट्रीम करण्यासाठी असिंक इटरेटर वापरला जाऊ शकतो आणि प्रत्येक कोटवर प्रक्रिया करण्यासाठी असिंक 'फॉर ईच' वापरला जाऊ शकतो, ज्यामुळे वापरकर्त्याच्या इंटरफेसला नवीनतम किमतींसह अद्यतनित केले जाते. याचा उपयोग खालील कंपन्यांचे सध्याचे स्टॉक दर प्रदर्शित करण्यासाठी केला जाऊ शकतो:
- टेन्सेंट (चीन): एका मोठ्या आंतरराष्ट्रीय तंत्रज्ञान कंपनीचा स्टॉक डेटा मिळवणे
- टाटा कन्सल्टन्सी सर्व्हिसेस (भारत): एका अग्रगण्य आयटी सेवा कंपनीचे स्टॉक अपडेट्स प्रदर्शित करणे
- सॅमसंग इलेक्ट्रॉनिक्स (दक्षिण कोरिया): जागतिक इलेक्ट्रॉनिक्स उत्पादकाचे स्टॉक दर दर्शवणे
- टोयोटा मोटर कॉर्पोरेशन (जपान): आंतरराष्ट्रीय ऑटो उत्पादकाच्या स्टॉक किमतींचे निरीक्षण करणे
निष्कर्ष
असिंक इटरेटर्स आणि असिंक 'फॉर ईच' हेल्पर जावास्क्रिप्टमध्ये असिंक्रोनसपणे डेटा स्ट्रीम्सवर प्रक्रिया करण्याचा एक शक्तिशाली आणि मोहक मार्ग प्रदान करतात. पुनरावृत्ती तर्क (iteration logic) गुंडाळून, तुम्ही तुमचा कोड सोपा करू शकता, वाचनीयता सुधारू शकता आणि तुमच्या ऍप्लिकेशन्सचे कार्यप्रदर्शन वाढवू शकता. त्रुटी हाताळून, समवर्तीता नियंत्रित करून आणि रद्द करणे सक्षम करून, तुम्ही मजबूत आणि स्केलेबल असिंक्रोनस डेटा प्रोसेसिंग पाइपलाइन्स तयार करू शकता.